
#include "stdafx.h"
#include "..\Lab2_GOST\GOST_Cipher.h" // for auth
#include "..\Lab2_GOST\GOST_Cipher.cpp" 
/* http://www2.crypto.rub.de/imperia/md/content/seminare/itsss09/subliminal_channels.pdf */
#include "..\Lab5_EDS_DSA\DSA_System.h" // for hidden channel
#include "..\Lab5_EDS_DSA\DSA_System.cpp"
#include "..\Lab5_EDS_DSA\DSA_signer.cpp" 


#include <algorithm>
using std::for_each;

unsigned __int64 block2UI64(const block& bl)
{
	unsigned __int64 res = bl.l;
	res <<= sizeof(bl.r)*8;
	res += bl.r;
	return res;
}

int main(int argc, char* argv[])
{
	srand(unsigned(time(NULL)));

	printf("\nStep 1\n");
	// handshake with symmetric encryption
	const int KEY_LENGTH = 8;
	uint K1[8];// = {34545,90881,234989,43250,483091,23047,120485,904357};
	
	for_each(K1, K1 + KEY_LENGTH, [](uint& n) mutable
	{
		n = rand();
	});
	GOST_Cipher cipher(K1);

	printf("Key for handshake authentication: \n(");
	for_each(K1, K1 + KEY_LENGTH, [](uint n)
	{
		printf("%u\t",n);
	});
	printf(")\n");

	// B sends to A random number, need to be encipher
	block random_for_auth;
	random_for_auth.l = rand();
	random_for_auth.r = rand();
	printf("B -> A: r = %I64u\n", block2UI64(random_for_auth));

	text et;
	et.push_back(random_for_auth);
	block encipered_random = (*cipher.Encipher(et))[0];

	// A sends to B ciphered r
	printf("A -> B: r' = E(r) = %I64u\n", block2UI64(encipered_random));

	text dt;
	dt.push_back(encipered_random);
	block deciphered_random = (*cipher.Decipher(dt))[0];

	// B deciphers received number
	printf("B: r'' = D(r') = %I64u\n", block2UI64(deciphered_random));
	bool is_friend = random_for_auth == deciphered_random;
	printf("B: \"A is a %s\"\n", is_friend ? "friend. Continue talking.":"foe");

	if(!is_friend) return 0;




	printf("\nStep 2\n");
	DSA_System dsa;
	large_uint K2 = large_uint::random() % (dsa.get_p() - 1) + 1;
	printf("Key for signing: (%I64u; %I64u)\n", K2._h, K2._l);

	large_uint message = large_uint::random(), hidden_message = large_uint::random() %  (dsa.get_q() - 1) + 1;

	DSA_signer signer = dsa.add_signer(K2);

	printf("Message = (%I64u; %I64u)\n", message._h, message._l);
	printf("Hidden message = (%I64u; %I64u)\n", hidden_message._h, hidden_message._l);

	// B sends his signature with subliminal message to A
	DSA_signature sign = signer.get_signature_with_subliminal_channel(message, hidden_message);
	printf("B -> A: M = (%I64u; %I64u), r = (%I64u; %I64u), s = (%I64u; %I64u)\n", message._h, message._l, sign.r._h, sign.r._l, sign.s._h, sign.s._l);

	// A verifying the signature
	bool res = dsa.verify(0, message, sign);
	printf("A: \"signature is%s verified\"\n", res? "": " not");
	
	// A restoring the subliminal message
	large_uint restored_hidden = dsa.get_subliminal_message(K2, message, sign);
	printf("A: \"subliminal message is (%I64u; %I64u)\"\n", restored_hidden._h, restored_hidden._l);
	
	printf("Restored is %s\n", (hidden_message == restored_hidden) ? "succesfull" : "failed");

	return 0; 
}
  